#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""
Reads the commands from the str_canavas module and plots the stereographic 
diagram via pyCairo and save it to a file.
"""

from math import pi, sin, cos, radians

def plot_diagram(Comands, file_name, radius = 200, title='', comments='', count=0, density=None, dsize=None, fdensity=None, stress_commands=None, stress=None, isblank=None, whitespaces=2.4):
    height, width = radius*whitespaces, radius*whitespaces  
    cx, cy = width/2, height/2
    
    import cairo
    
    surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, int(width), int(height))
    ctx = cairo.Context(surface)
    
    ctx.set_source_rgb (1, 1, 1)
    ctx.set_operator (cairo.OPERATOR_SOURCE)
    ctx.paint()
    
    if density:
        plot_density(density, ctx, radius, cx, cy, dsize)
    
    if fdensity:
        plot_fdensity(fdensity, ctx, radius, cx, cy)
        plot_isolines(fdensity, ctx, radius, cx, cy)

    draw_Frame(ctx, radius, cx, cy)
    
    for cmds in Comands:
        for cmd in cmds:
            if cmd[0] == 'point':
                x, y = recalc_coords(cmd[1][0], cmd[1][1], cx, cy, radius)
                draw_Point(ctx, x, y, cmd[2])
            elif cmd[0] == 'line':
                x1, y1 = recalc_coords(cmd[1][0], cmd[1][1], cx, cy, radius)
                x2, y2 = recalc_coords(cmd[1][2], cmd[1][3], cx, cy, radius)
                draw_Line(ctx, 
                          x1, y1, x2, y2, cmd[2])
            else:
                import sys
                #sys.stdout.write('WARNING! Cannot recognize %s method\n' %
                #                                                         cmd[0])
    
    for cmds in stress_commands:
        for cmd in cmds:
            if cmd[0] == 'point':
                x, y = recalc_coords(cmd[1][0], cmd[1][1], cx, cy, radius)
                draw_Point(ctx, x, y, [0,0,0], r=6)
            elif cmd[0] == 'line':
                x1, y1 = recalc_coords(cmd[1][0], cmd[1][1], cx, cy, radius)
                x2, y2 = recalc_coords(cmd[1][2], cmd[1][3], cx, cy, radius)
                draw_Line(ctx, 
                          x1, y1, x2, y2, cmd[2])
            else:
                import sys
                #sys.stdout.write('WARNING! Cannot recognize %s method\n' %
                #                                                         cmd[0])

    if stress:
        # draw stress arrows
        s1 = stress[0]; s3 = stress[2]
        st3_1_x = cx + sin(radians(s3[0]))*radius*1.1
        st3_1_y = cy - cos(radians(s3[0]))*radius*1.1
        st3_o_y = cy - cos(radians(s3[0]))*radius*1.2
        st3_o_x = cx + sin(radians(s3[0]))*radius*1.2
        st3_2_x = st3_o_x + sin(radians(s3[0]+90))*radius*.05
        st3_2_y = st3_o_y - cos(radians(s3[0]+90))*radius*.05
        st3_3_x = st3_o_x + sin(radians(s3[0]-90))*radius*.05
        st3_3_y = st3_o_y - cos(radians(s3[0]-90))*radius*.05

        ctx.set_source_rgb(0,0,0)
        ctx.set_line_width (1)
        ctx.move_to(st3_1_x, st3_1_y)
        ctx.line_to(st3_2_x, st3_2_y)
        ctx.line_to(st3_3_x, st3_3_y)
        ctx.line_to(st3_1_x, st3_1_y)
        ctx.fill_preserve()
        ctx.set_source_rgb(1,1,1)
        ctx.stroke()


        s3[0]+=180
        st3_1_x = cx + sin(radians(s3[0]))*radius*1.1
        st3_1_y = cy - cos(radians(s3[0]))*radius*1.1
        st3_o_y = cy - cos(radians(s3[0]))*radius*1.2
        st3_o_x = cx + sin(radians(s3[0]))*radius*1.2
        st3_2_x = st3_o_x + sin(radians(s3[0]+90))*radius*.05
        st3_2_y = st3_o_y - cos(radians(s3[0]+90))*radius*.05
        st3_3_x = st3_o_x + sin(radians(s3[0]-90))*radius*.05
        st3_3_y = st3_o_y - cos(radians(s3[0]-90))*radius*.05

        ctx.set_source_rgb(0,0,0)
        ctx.set_line_width (1)
        ctx.move_to(st3_1_x, st3_1_y)
        ctx.line_to(st3_2_x, st3_2_y)
        ctx.line_to(st3_3_x, st3_3_y)
        ctx.line_to(st3_1_x, st3_1_y)
        ctx.fill_preserve()
        ctx.set_source_rgb(1,1,1)
        ctx.stroke()
        
        st1_1_x = cx + sin(radians(s1[0]))*radius*1.2
        st1_1_y = cy - cos(radians(s1[0]))*radius*1.2
        st1_o_y = cy - cos(radians(s1[0]))*radius*1.1
        st1_o_x = cx + sin(radians(s1[0]))*radius*1.1
        st1_2_x = st1_o_x + sin(radians(s1[0]+90))*radius*.05
        st1_2_y = st1_o_y - cos(radians(s1[0]+90))*radius*.05
        st1_3_x = st1_o_x + sin(radians(s1[0]-90))*radius*.05
        st1_3_y = st1_o_y - cos(radians(s1[0]-90))*radius*.05

        ctx.set_source_rgb(1,1,1)
        ctx.set_line_width (1)
        ctx.move_to(st1_1_x, st1_1_y)
        ctx.line_to(st1_2_x, st1_2_y)
        ctx.line_to(st1_3_x, st1_3_y)
        ctx.line_to(st1_1_x, st1_1_y)
        ctx.fill_preserve()
        ctx.set_source_rgb(0,0,0)
        ctx.stroke()

        s1[0]+=180
        st1_1_x = cx + sin(radians(s1[0]))*radius*1.2
        st1_1_y = cy - cos(radians(s1[0]))*radius*1.2
        st1_o_y = cy - cos(radians(s1[0]))*radius*1.1
        st1_o_x = cx + sin(radians(s1[0]))*radius*1.1
        st1_2_x = st1_o_x + sin(radians(s1[0]+90))*radius*.05
        st1_2_y = st1_o_y - cos(radians(s1[0]+90))*radius*.05
        st1_3_x = st1_o_x + sin(radians(s1[0]-90))*radius*.05
        st1_3_y = st1_o_y - cos(radians(s1[0]-90))*radius*.05

        ctx.set_source_rgb(1,1,1)
        ctx.set_line_width (1)
        ctx.move_to(st1_1_x, st1_1_y)
        ctx.line_to(st1_2_x, st1_2_y)
        ctx.line_to(st1_3_x, st1_3_y)
        ctx.line_to(st1_1_x, st1_1_y)
        ctx.fill_preserve()
        ctx.set_source_rgb(0,0,0)
        ctx.stroke()

    if not isblank:    
        # plot title
        ctx.set_source_rgb(0, 0, 0)
        ctx.select_font_face("Arial",
                                cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
        ctx.set_font_size(18)
        ctx.move_to(10, 18)
        ctx.show_text(title)
        
        # plot the number of the planes
        if count:
            ctx.select_font_face("Arial",
                                cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
            ctx.set_font_size(10)
            ctx.move_to(cx+0.8*radius, height-35)
            ctx.show_text('n: %s' % count)
        
        # plot comments
        ctx.select_font_face("Arial",
                                cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
        ctx.set_font_size(10)
        ctx.move_to(10, height-20)
        ctx.show_text(comments)
    
    
    surface.write_to_png(file_name)
     
    
        
    


def draw_Frame(ctx, r, cx, cy):
    ctx.arc(cx, cy, r, 0, 2 * pi)
    ctx.set_source_rgb(0.5, 1, 1)
    #ctx.fill_preserve()
    ctx.set_source_rgb(0, 0, 0)
    ctx.set_line_width(4)
    ctx.stroke()
    ctx.move_to(cx, cy-r)
    ctx.line_to(cx, cy-r-10)
    ctx.stroke()
    ctx.move_to(cx-5, cy); ctx.line_to(cx+5, cy); ctx.stroke()
    ctx.move_to(cx, cy-5); ctx.line_to(cx, cy+5); ctx.stroke()


def draw_Point(ctx, x, y, col, linewidth=2, r=5):
    ctx.set_source_rgb(col[0], col[1], col[2])
    ctx.set_line_width (linewidth)
    ctx.move_to(x + r, y)
    ctx.arc(x, y, r, 0, 2 * pi)    
    ctx.fill_preserve()
    ctx.set_source_rgb(1,1,1)
    ctx.stroke() 


def draw_Line(ctx, x1, y1, x2, y2, col, linewidth=1):        
    ctx.set_source_rgb(col[0], col[1], col[2])
    ctx.set_line_width (linewidth)
    ctx.move_to(x1, y1)
    ctx.line_to(x2, y2)        
    ctx.stroke()

def draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col):
    ctx.set_source_rgb(col[0], col[1], col[2])
    ctx.set_line_width (0)
    ctx.move_to(x1, y1)
    ctx.line_to(x2, y2)
    ctx.line_to(x3, y3)
    ctx.line_to(x4, y4)
    ctx.line_to(x1, y1)
    ctx.fill_preserve()
    ctx.set_source_rgb(1,1,1)
    ctx.stroke()
    
def recalc_coords(x, y, cx, cy, r):
    x1 = x*r + cx
    y1 = y*r + cy
    return x1, y1

def plot_density(density, ctx, r, cx, cy, cell_size):
    from plane import Plane
    for pl in density:        
        pln = Plane(pl[0], pl[1])
        col = [1-pl[2]] * 3
        #x,y = recalc_coords(pln.cos3, (-1)*pln.cos1, cx, cy, r)
        #draw_Point(ctx, x, y,col,0)
        
        pln1 = Plane(0, 0); pln2 = Plane(0, 0)
        pln3 = Plane(0, 0); pln4 = Plane(0, 0)        
        pln1.dir, pln1.dip = pln.dir + cell_size/2.0, pln.dip + cell_size/2.0
        pln2.dir, pln2.dip = pln.dir + cell_size/2.0, pln.dip - cell_size/2.0
        pln3.dir, pln3.dip = pln.dir - cell_size/2.0, pln.dip - cell_size/2.0
        pln4.dir, pln4.dip = pln.dir - cell_size/2.0, pln.dip + cell_size/2.0
        x1,y1 = recalc_coords(pln1.cos3, (-1)*pln1.cos1, cx, cy, r)
        x2,y2 = recalc_coords(pln2.cos3, (-1)*pln2.cos1, cx, cy, r)
        x3,y3 = recalc_coords(pln3.cos3, (-1)*pln3.cos1, cx, cy, r)
        x4,y4 = recalc_coords(pln4.cos3, (-1)*pln4.cos1, cx, cy, r)
        draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col)
        
def plot_fdensity(fdensity, ctx, r, cx, cy):
    cell_size = 2.0*r/len(fdensity)
    for x_ in range(0, len(fdensity)):
        for y_ in range(0, len(fdensity[x_])):
            x,y = cx-(x_*2)*r/len(fdensity)+r,cy-r+(y_*2)*r/len(fdensity[x_])
            col=[1-fdensity[x_][y_]]*3
            x1, y1 = x-cell_size/2.0, y-cell_size/2.0
            x2, y2 = x-cell_size/2.0, y+cell_size/2.0
            x3, y3 = x+cell_size/2.0, y+cell_size/2.0
            x4, y4 = x+cell_size/2.0, y-cell_size/2.0
            draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col)   

            
def plot_isolines(fdensity, ctx, r, cx, cy):
    import isolines
    cell_size = 2.0*r/len(fdensity)
    
    # list of intervals
    intervals= [x/100.0 for x in range(0,100,5)]
    
    # doing isolines
    prepared_matrix=isolines.prepare_matrix(fdensity)    
    calculated_dots=isolines.calculate_dots(prepared_matrix,intervals)
    coords=isolines.calculate_coords(calculated_dots)
    
    # drawing
    lx=len(fdensity)
    ly=len(fdensity[0])    
    for cell in coords:        
        for edge in cell:
            y1,x1 = edge[1], edge[2]
            y2,x2 = edge[3], edge[4]
            x1_,y1_ = cx-(x1*2)*r/lx+r,cy-r+(y1*2)*r/ly        
            x2_,y2_ = cx-(x2*2)*r/lx+r,cy-r+(y2*2)*r/ly
            col = [0,0,0]
            draw_Line(ctx, x1_, y1_, x2_, y2_, col, linewidth=0.4) 

